/* 
 * TesteController.java
 * Copyright (c) Faculdade Anhanguera de Anápolis.
 * Tecnologia em Análise e Desenvolvimento de Sistemas.
 * Projeto Multidisciplinar de Autoaprendizagem.
 *
 * Este software é confidencial e propriedade da Faculdade Anhanguera de Anápolis.
 * Não é permitida sua distribuição ou divulgação do seu conteúdo sem expressa autorização da Faculdade Anhanguera de Anápolis.
 * Este arquivo contém informações proprietárias.
 */
package br.com.pma.chamatec.dao;

import java.io.Serializable;

import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import javax.persistence.PersistenceContext;

import br.com.pma.entity.IEntity;

/**
 * Classe padrão dos DAOs da aplicação.
 * 
 * @author Ludemeula Fernandes de Sá
 */
public abstract class GenericDAO<E extends IEntity> implements Serializable {
	private static final long serialVersionUID = 4486182953183310956L;

	@PersistenceContext(unitName="chamatec")

	private EntityManager entityManager;
	private Class<E> clazz = null;
	
	/**
	 * Obtem o EntityManager.
	 * 
	 * @return EntityManager
	 */
	public EntityManager getEntityManager() {
		return entityManager;
	}

	/**
	 * Recebe o entity manager qualificado (chamatec).
	 * 
	 * @param entityManger
	 */
	protected void setEntityManger(EntityManager entityManger){
		this.entityManager = entityManger;
	}

	/**
	 * Retorna a classe "genérica".
	 * 
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	protected Class<E> getClazz() {
		if (this.clazz == null) {
			this.clazz = ((Class) ((java.lang.reflect.ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
		}
		return this.clazz;
	}
	
	/**
	 * Recupera entidade por PK.
	 * 
	 * @param entity
	 * @return E
	 */
	public E findByPrimaryKey(E entity) {
		return getEntityManager().find(getClazz(), entity.getId());
	}

	/**
	 * Recupera entidade por PK sem cache.
	 * 
	 * @param entity
	 * @return
	 */
	public E findByPrimaryKeyWithoutCache(E entity) {
		clear();
		return getEntityManager().find(getClazz(), entity.getId());
	}
	
	/**
	 * Persiste entidade.
	 * 
	 * @param entity
	 */
	public void persist(E entity) {
		getEntityManager().persist(entity);
	}

	/**
	 * Atualiza entidade.
	 * 
	 * @param entity
	 * @return E
	 */
	public E merge(E entity) {
		if (!contains(entity)) {
			return getEntityManager().merge(entity);
		}
		return entity;
	}

	/**
	 * Remove Entidade.
	 * 
	 * @param entity
	 */
	public void remove(E entity) {
		entity = findByPrimaryKey(entity);
		if (contains(entity)) {
			getEntityManager().remove(entity);
		}
	}

	/**
	 * Faz uma atualização da entidade.
	 * 
	 * @param entity
	 */
	public void refresh(E entity) {
		getEntityManager().refresh(entity);
	}

	/**
	 * Faz uma atualização da entidade fazendo lock.
	 * @param entity
	 */
	public void refreshAndLock(E entity) {
		getEntityManager().refresh(entity, LockModeType.WRITE);
	}

	/**
	 * Verifica se o objeto está na "sessão".
	 * 
	 * @param entity
	 * @return
	 */
	public boolean contains(E entity) {
		return getEntityManager().contains(entity);
	}

	/**
	 * Limpa a "sessão". 
	 */
	public void clear() {
		getEntityManager().clear();
	}

	/**
	 * Executa as modificacoes no banco de dados
	 */
	public void flush() {
		getEntityManager().flush();
	}

	/**
	 * "Junta" transaçoes.
	 */
	public void joinTransaction() {
		getEntityManager().joinTransaction();
	}
}